home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / dosutil / tr.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  4KB  |  226 lines

  1. /* tr - like unix tr
  2.  
  3. ** THIS PROGRAM MUST BE COMPILED WITH THE EXTENDED PREPROCESSOR
  4. ** IE: cc TR -p
  5.  
  6.  by jim mckim
  7.  
  8.  this program may be used in several ways.  By example:
  9.  
  10.      tr A-Z a-z <input >output
  11.     will convert upper case to lower case
  12.  
  13.     tr -c !-~ ? <input >output
  14.     will convert unprintable characters to question marks
  15.  
  16.     tr -cs !-~ \40 <input >output
  17.     will convert unprintable characters to spaces and squeeze out extra spaces
  18.  
  19.     tr -d \177-\377 <input
  20.     will remove all characters whose eighth bit is set
  21.  
  22.  comments about this can reach me via BIX (jmckim)
  23.  or telephone (216 835 3845)
  24.  or USPS
  25.  (Jim McKim
  26.  30224 Wolf Rd.
  27.  Bay Village, OH 44140)
  28.  
  29.  (i gladly accept bug reports; bug fixes will make me ecstatic)
  30.  
  31. Compile command: cc tr -fop
  32. */
  33.  
  34. #include <stdio.h>
  35. #include <file.h>
  36.  
  37. #define TTSIZE 257
  38. #define isodigit(c) ((c)>='0' && (c)<='7')
  39.  
  40. TellHow()
  41. {
  42. fputs("usage: tr [-flags] string1 string2 <input >output\n", stderr);
  43. fputs("where flags are:\n",stderr);
  44. fputs("c  compliment string1 (e.g. all NOT in string1)\n",stderr);
  45. fputs("d  delete if in string1\n",stderr);
  46. fputs("s  squeeze out duplicates if in string2\n",stderr);
  47. fputs("r  raw (no cr/lf conversion) (MSDOS only)\n",stderr);
  48. exit(-1);
  49. }
  50.  
  51. Interpret(input,output)
  52. char *input, *output;
  53. {
  54.     int startc, endc;
  55.     int i;
  56.     int range_flag;  /* true when '-' has been seen */
  57.     int got_next;  /* true when char after '-' has been seen */
  58.  
  59.     *output = range_flag = got_next = 0;
  60.     while (*input)
  61.     {
  62.         if (*input == '\\')
  63.         {
  64.             ++input;
  65.             if (isodigit(*input))
  66.             {
  67.                 /* got an octal constant */
  68.                 i = *input - '0';
  69.                 if (isodigit(*(input+1)))
  70.                 {
  71.                     i = i*8 + *++input - '0';
  72.                     if (isodigit(*(input+1)))
  73.                         i = i*8 + *++input - '0';
  74.                 }
  75.                 *output++ = i;
  76.                 if (range_flag)
  77.                     got_next = 1;
  78.             }
  79.             else
  80.             {
  81.                 /* got a \c type character */
  82.                 *output++ = *input;
  83.                 if (range_flag)
  84.                     got_next = 1;
  85.             }
  86.         }
  87.         else if (*input == '-')
  88.         {
  89.             /* got a range */
  90.             range_flag = 1;
  91.         }
  92.         else
  93.         {
  94.             /* got a normal character */
  95.             *output++ = *input;
  96.             if (range_flag)
  97.                 got_next = 1;
  98.         }
  99.  
  100.         ++input;
  101.  
  102.         if (range_flag && got_next)
  103.         {
  104.             startc = *(output-2);
  105.             endc = *(output-1);
  106.             output -= 2;
  107.             for (i=startc; i<=endc; ++i)
  108.                 *output++ = i;
  109.             range_flag = got_next = 0;
  110.         }
  111.     } /* end while */
  112.     *output = '\0';
  113. }
  114.  
  115. main(argc,argv)
  116. int argc;
  117. char *argv[];
  118. {
  119.     char incode[TTSIZE], outcode[TTSIZE], trtbl[TTSIZE];
  120.     char inset[TTSIZE];
  121.     char inch, outch, old_outch;
  122.     int i, j, iarg;
  123.     char c_flag, d_flag, s_flag;
  124.     char *iap;
  125.  
  126.     iarg = 1;
  127.     c_flag = d_flag = s_flag = 0;
  128.  
  129.     /* get the switches */
  130.     while ((iarg <= argc) && (*argv[iarg] == '-'))
  131.     {
  132.         iap = argv[iarg++] + 1;  /* point past '-' */
  133.         while (*iap)
  134.             switch (*iap++)
  135.             {
  136.             case 'c':    /* Compliment string */
  137.                 c_flag = 1;
  138.                 break;
  139.             case 'd':    /* Delete */
  140.                 d_flag = 1;
  141.                 break;
  142.             case 's':    /* Squeeze out duplicates */
  143.                 s_flag = 1;
  144.                 break;
  145.             case 'r':    /* Raw I/O mode */
  146.                 *stdin |= F_BINARY;
  147.                 *stdout |= F_BINARY;
  148.                 break;
  149.             default:
  150.                 TellHow();
  151.             }
  152.     }
  153.  
  154.     if (iarg+1 >= argc)
  155.     {
  156.         TellHow();
  157.     }
  158.  
  159.     for (i=0; i<TTSIZE; ++i)
  160.     {
  161.         trtbl[i] = i;
  162.         inset[i] = '\0';
  163.         incode[i] = '\0';
  164.         outcode[i] = '\0';
  165.     }
  166.  
  167.     Interpret(argv[iarg++],incode);
  168.     Interpret(argv[iarg],outcode);
  169.  
  170.     i = 0;
  171.     j = 0;
  172.     while (incode[i])
  173.     {
  174.         inset[incode[i]] = 1;
  175.         if (c_flag == 0)
  176.         {
  177.             trtbl[incode[i]] = outcode[j];
  178.             /* if next is null, dup last */
  179.             if (outcode[j+1])
  180.                 ++j;
  181.         }
  182.         ++i;
  183.     }
  184.  
  185.     if (c_flag == 1)
  186.     {
  187.         j = 0;
  188.         for (i=0; i<TTSIZE; ++i)
  189.         {
  190.             if (inset[i] == 0)
  191.             {
  192.                 inset[i] = 1;
  193.                 trtbl[i] = outcode[j];
  194.                 if (outcode[j+1])
  195.                     ++j;
  196.             }
  197.             else
  198.             {
  199.                 inset[i] = 0;
  200.                 trtbl[i] = i;
  201.             }
  202.         }
  203.     }
  204.  
  205. /* To speed up processsing, switch stdio streams to buffered */
  206.     stdin = setbuf(stdin, 1024);
  207.     stdout = setbuf(stdout, 1024);
  208.  
  209.     outch = '\0';
  210.     while ((inch=getc(stdin)) != EOF)
  211.     {
  212.         old_outch = outch;
  213.         outch = trtbl[inch];
  214.         if (d_flag)
  215.             if (inset[inch])
  216.                 continue;
  217.         if (s_flag)
  218.             if (inset[inch])
  219.                 if (old_outch == outch)
  220.                     continue;
  221.         putc(outch, stdout);
  222.     }
  223.  
  224.     fflush(stdout);        /* Insure output buffer is written */
  225. }
  226.